﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.IO;
using WMPLib;
using System.Diagnostics;

namespace PlaylistGenerator_v2._0
{
    public partial class FormPlaylist : Form
    {
        #region Variáveis e Constantes
        private static String pastaTemp = Environment.GetEnvironmentVariable("Temp");
        private static String pastaLocal = Environment.CurrentDirectory;
        private static String nomeDoArquivoXML = "\\MediaPlayerDados.xml";
        private static String arquivoTemp = pastaTemp + nomeDoArquivoXML;
        private static String arquivoLocal = pastaLocal + nomeDoArquivoXML;
        private static String pastaMusicaLocal = pastaLocal + "\\MUSICAS";
        private static String pastaComercialLocal = pastaLocal + "\\COMERCIAIS";
        private Image logo = global::PlaylistGenerator_v2._0.Resource.home;
        private Image play = global::PlaylistGenerator_v2._0.Resource.playButton;
        private Image pause = global::PlaylistGenerator_v2._0.Resource.pauseButton;
        private Image stop = global::PlaylistGenerator_v2._0.Resource.stopButton;
        private Image previous = global::PlaylistGenerator_v2._0.Resource.previousButton;
        private Image next = global::PlaylistGenerator_v2._0.Resource.nextButton;
        private Boolean isPlayButton;
        private Hashtable pastasDeArquivos;
        private Random random = new Random();
        private Timer timer;
        private List<String> musicasDoPlaylist;
        public List<String> MusicasDoPlaylist
        {
            get {
                if (musicasDoPlaylist == null && mediaPlayer.currentPlaylist.count > 0)
                {
                    musicasDoPlaylist = new List<String>();
                    for (int i = 0; i < mediaPlayer.currentPlaylist.count; i++)
                    {
                        musicasDoPlaylist.Add(mediaPlayer.currentPlaylist.get_Item(i).sourceURL);
                    }
                }
                return musicasDoPlaylist;
            }
        }
        #endregion

        #region Inicialização e Configurações
        public FormPlaylist()
        {
            InitializeComponent();
            splitControlesPlayer.Panel2Collapsed = true;
            ajustaDisplay(lblMusica, "");
            ajustaDisplay(txtTimeElapsed, "");
            listPastas.DisplayMember = "nomeDaPasta";
            isPlayButton = true;
            mediaPlayer.CurrentItemChange +=
                new AxWMPLib._WMPOCXEvents_CurrentItemChangeEventHandler(trocaFaixa);
            recuperaDadosDoArquivo();
        }
        #endregion

        #region Listeners Controles
        private void btnAdicionaMusica_Click(object sender, EventArgs e)
        {
            inserePasta(listPastas, TipoPasta.MUSICA, pastaMusicaLocal);
        }

        private void btnAdicionaComercial_Click(object sender, EventArgs e)
        {
            inserePasta(listPastas, TipoPasta.COMERCIAL, pastaComercialLocal);
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            listPastas.Items.Remove(listPastas.SelectedItem);
            controlVisible(btnIniciaPlayer, listPastas.Items.Count > 0);
        }

        private void btnOrdenaMais_Click(object sender, EventArgs e)
        {
            ordenaItem(listPastas, -1);
        }

        private void btnOrdenaMenos_Click(object sender, EventArgs e)
        {
            ordenaItem(listPastas, 1);
        }

        private void btnIniciaPlayer_Click(object sender, EventArgs e)
        {
            listPastas.SelectedIndex = -1;
            splitControlesPlayer.Panel2Collapsed = !splitControlesPlayer.Panel2Collapsed;
            controlVisible(btnAdicionaMusica, splitControlesPlayer.Panel2Collapsed);
            controlVisible(btnAdicionaComercial, splitControlesPlayer.Panel2Collapsed);
            controlVisible(btnRemove, splitControlesPlayer.Panel2Collapsed);
            controlVisible(btnOrdenaMais, splitControlesPlayer.Panel2Collapsed);
            controlVisible(btnOrdenaMenos, splitControlesPlayer.Panel2Collapsed);
            controlEnabled(listPastas, splitControlesPlayer.Panel2Collapsed);
            buttonText(btnIniciaPlayer, splitControlesPlayer.Panel2Collapsed, "INICIAR PLAYER", "FECHAR PLAYER");
            isPlayButton = !splitControlesPlayer.Panel2Collapsed;
            buttonImage(btnPlayPause, isPlayButton, play, pause);

            if (!splitControlesPlayer.Panel2Collapsed)
            {
                List<Pasta> pastas = getPastasDoListBox(listPastas);
                registraPastas(pastas);
                montaPlaylist(pastas);
                ajustaVolume(mediaPlayer.settings.volume);
                volume.Value = Convert.ToInt16((Convert.ToDouble(mediaPlayer.settings.volume) / 100) * 20);
                GeradorDeXml.geraXml(arquivoLocal, pastas);
                GeradorDeXml.geraXml(arquivoTemp, pastas);
                btnPlayPause_Click(null, null);
            }
            else
            {
                if (timer != null)
                {
                    timer.Stop();
                    timer = null;
                }
                mediaPlayer.Ctlcontrols.stop();
                mediaPlayer.currentPlaylist.clear();
                ajustaDisplay(lblMusica, "");
                ajustaDisplay(txtTimeElapsed, "");
                buttonImage(btnPlayPause, true, play, pause);
                controlVisible(btnRemove, listPastas.SelectedIndex > -1);
                controlVisible(btnOrdenaMais, listPastas.SelectedIndex > -1);
                controlVisible(btnOrdenaMenos, listPastas.SelectedIndex > -1);
            }

        }

        private void listPastas_SelectedIndexChanged(object sender, EventArgs e)
        {
            controlVisible(btnRemove, listPastas.SelectedIndex > -1);
            controlVisible(btnOrdenaMais, listPastas.SelectedIndex > 0);
            controlVisible(btnOrdenaMenos, listPastas.SelectedIndex > -1 && listPastas.SelectedIndex < listPastas.Items.Count - 1);
        }
        #endregion

        #region Listeners Player
        private void btnPlayPause_Click(object sender, EventArgs e)
        {
            if (isPlayButton)
            {
                mediaPlayer.Ctlcontrols.play();
                if (timer != null)
                {
                    timer.Start();
                }
            }
            else
            {
                mediaPlayer.Ctlcontrols.pause();
                if (timer != null)
                {
                    timer.Stop();
                }
            }
            isPlayButton = !isPlayButton;
            buttonImage(btnPlayPause, isPlayButton, play, pause);
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            isPlayButton = true;
            buttonImage(btnPlayPause, isPlayButton, play, pause);
            mediaPlayer.Ctlcontrols.stop();
            ajustaDisplay(lblMusica, "");
            if (timer != null)
            {
                timer.Stop();
            }
            ajustaDisplay(txtTimeElapsed, "");
        }

        private void btnAnterior_Click(object sender, EventArgs e)
        {
            mediaPlayer.Ctlcontrols.previous();
        }

        private void btnProximo_Click(object sender, EventArgs e)
        {
            mediaPlayer.Ctlcontrols.next();
        }
        
        private void volume_Scroll(object sender, EventArgs e)
        {
            ajustaVolume(Convert.ToInt16(((Convert.ToDouble(volume.Value) * 10) / 200) * 100));
        }
        #endregion

        #region Manipuladores de controles
        private void buttonText(Button botao, Boolean isTrue, String txtTrue, String txtFalse)
        {
            botao.Text = isTrue ? txtTrue : txtFalse;
            botao.BackColor = isTrue ? Color.DarkBlue : Color.Red;
        }

        private void buttonImage(Button botao, Boolean isTrue, Image imgTrue, Image imgFalse)
        {
            botao.BackgroundImage = isTrue ? imgTrue : imgFalse;
        }

        private void controlEnabled(Control controle, Boolean isTrue)
        {
            controle.Enabled = isTrue;
        }

        private void controlVisible(Control controle, Boolean isTrue)
        {
            controle.Visible = isTrue;
        }

        private void ordenaItem(ListBox list, int indexAuxiliar)
        {
            int index = list.SelectedIndex;
            Object itemAtual = list.SelectedItem;

            bool condicao = false;

            switch (indexAuxiliar)
            {
                case -1:
                    condicao = index > 0;
                    break;
                case 1:
                    condicao = index < (list.Items.Count - 1);
                    break;
            }

            if ((list.Items.Count > 1) && (condicao))
            {
                Object itemAuxiliar = list.Items[index + indexAuxiliar];
                list.Items[index] = itemAuxiliar;
                list.Items[index + indexAuxiliar] = itemAtual;
                list.SelectedIndex = index + indexAuxiliar;
            }
        }
        #endregion

        #region Engine Controles
        private void inserePasta(ListBox list, TipoPasta tipo, String folder)
        {/*
            DialogResult result = folderDialog.ShowDialog();
            String path = folderDialog.SelectedPath;
            if (result.Equals(DialogResult.OK) && isPastaValida(path))
            {
                Pasta pasta = new Pasta(path, tipo);
                list.Items.Add(pasta);
                controlVisible(btnIniciaPlayer, listPastas.Items.Count > 0);
            }*/
            new FormAdicionaPasta(folder, tipo, this).Show();
            this.Enabled = false;
        }

        public void adicionaPasta(Pasta pasta)
        {
            listPastas.Items.Add(pasta);
            controlVisible(btnIniciaPlayer, listPastas.Items.Count > 0);
        }

        private bool isPastaValida(String path)
        {
            bool isValida = false;
            foreach (String arquivo in Directory.GetFiles(path))
            {
                if (isExtensaoValida(Path.GetExtension(arquivo)))
                {
                    isValida = true;
                    break;
                }
            }
            if (!isValida)
            {
                MessageBox.Show("Essa pasta não contém arquivos multimidia compatíveis!");
            }
            return isValida;
        }

        private bool isExtensaoValida(String extensao)
        {
            extensao = extensao.Replace(".", "").ToUpper();
            return extensao.Contains("MP3")
                || extensao.Contains("WMA")
                || extensao.Contains("WAV");
        }

        private void recuperaDadosDoArquivo()
        {
            List<Pasta> pastasRecuperadas = LeitorDeXml.getPastasDoArquivo(arquivoTemp);
            if (pastasRecuperadas.Count == 0)
            {
                pastasRecuperadas = LeitorDeXml.getPastasDoArquivo(arquivoLocal);
            }
            foreach (Pasta pasta in pastasRecuperadas)
            {
                listPastas.Items.Add(pasta);
            }
            controlVisible(btnIniciaPlayer, listPastas.Items.Count > 0);
        }
        #endregion

        #region Engine Player
        private List<Pasta> getPastasDoListBox(ListBox list)
        {
            List<Pasta> listaConvertida = new List<Pasta>();

            foreach (Pasta pasta in list.Items)
            {
                listaConvertida.Add(pasta);
            }

            return listaConvertida;
        }

        private void registraPastas(List<Pasta> pastas)
        {
            pastasDeArquivos = new Hashtable();
            foreach (Pasta pasta in pastas)
            {
                if (!pastasDeArquivos.ContainsKey(pasta))
                {
                    List<String> arquivos = recuperaArquivos(pasta);
                    if (arquivos.Count > 0)
                    {
                        pastasDeArquivos.Add(pasta, arquivos);
                    }
                }
            }
        }

        private List<String> recuperaArquivos(Pasta pasta)
        {
            List<String> arquivos = new List<String>();
            if (Directory.Exists(pasta.FolderPath))
            {
                foreach (String arquivo in Directory.GetFiles(pasta.FolderPath))
                {
                    if (isExtensaoValida(Path.GetExtension(arquivo)))
                    {
                        arquivos.Add(arquivo);
                    }
                }
            }
            else
            {
                MessageBox.Show("A pasta "
                    + pasta.FolderPath
                    + " não existe ou está inacessível!");
            }
            return arquivos;
        }

        private String getArquivo(Pasta pasta)
        {
            String arquivo = "";
            List<String> arquivos = (List<String>)pastasDeArquivos[pasta];
            if (arquivos != null)
            {
                if (arquivos.Count > 0)
                {
                    arquivo = arquivos[random.Next(0, arquivos.Count - 1)];
                    if (pasta.Tipo.Equals(TipoPasta.MUSICA))
                    {
                        arquivos.Remove(arquivo);
                    }
                }
                else
                {
                    pastasDeArquivos.Remove(pasta);
                    List<String> arquivosRecuperados = recuperaArquivos(pasta);
                    if (arquivosRecuperados.Count > 0)
                    {
                        pastasDeArquivos.Add(pasta, recuperaArquivos(pasta));
                        arquivo = getArquivo(pasta);
                    }
                }
            }
            return arquivo;
        }

        private void montaPlaylist(List<Pasta> pastas)
        {
            mediaPlayer.currentPlaylist.clear();
            for (int i = 0; i < 1000; i++)
            {
                IWMPPlaylist list = mediaPlayer.currentPlaylist;
                foreach (Pasta pasta in pastas)
                {
                    String arquivo = getArquivo(pasta);
                    if (arquivo.Length > 0)
                    {
                        IWMPMedia media = mediaPlayer.newMedia(arquivo);
                        list.appendItem(media);
                    }
                }
            }
        }

        private void trocaFaixa(object sender, AxWMPLib._WMPOCXEvents_CurrentItemChangeEvent evento)
        {
            AxWMPLib.AxWindowsMediaPlayer player = (AxWMPLib.AxWindowsMediaPlayer)sender;
            if (player.playState.Equals(WMPPlayState.wmppsTransitioning) || player.playState.Equals(WMPPlayState.wmppsPlaying))
            {
                timer = new Timer();
                timer.Interval = 1;
                timer.Tick += new EventHandler(gerenciaTime);
                timer.Start();
                
                IWMPMedia media = (IWMPMedia)player.currentMedia;
                String musica = Path.GetFileNameWithoutExtension(media.sourceURL);
                gerenciaHistorico("[" + DateTime.Now.ToShortTimeString() + "] " + musica);
                ajustaDisplay(lblMusica, musica);
                exibeProximaMusica(media);
            }
        }

        private void exibeProximaMusica(IWMPMedia media)
        {
            String musica = "";
            int indexAtual = MusicasDoPlaylist.IndexOf(media.sourceURL);
            if (indexAtual < MusicasDoPlaylist.Count - 1)
            {
                musica = Path.GetFileNameWithoutExtension(MusicasDoPlaylist[indexAtual+1]);
            }
            ajustaDisplay(lblProximaMusica, musica);
        }

        private void gerenciaTime(object sender, EventArgs e)
        {
            IWMPMedia media = (IWMPMedia)mediaPlayer.currentMedia;
            if (media != null)
            {
                ajustaDisplay(lblMusica, Path.GetFileNameWithoutExtension(media.sourceURL));

                String corrido = mediaPlayer.Ctlcontrols.currentPositionString;
                String total = mediaPlayer.currentMedia.durationString;
                ajustaDisplay(txtTimeElapsed, corrido + " / " + total);
            }
        }

        private void ajustaDisplay(DigitalDisplay display, String displayText)
        {
            display.Text = displayText;
            lblTocando.ForeColor = displayText.Length > 0 ? Color.Red : Color.Yellow;
        }

        private void ajustaDisplay(TextBox display, String displayText)
        {
            display.Text = displayText;
        }

        private void ajustaVolume(int valorVolume)
        {
            ajustaDisplay(txtVolume, "Volume: " + valorVolume.ToString() + " %");
            mediaPlayer.settings.volume = valorVolume;
        }

        private void gerenciaHistorico(String registro)
        {
            listHistorico.Items.Insert(0, registro);
        }
        #endregion

    }
}
